/**
 * 
 */
package routefinder.module;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Phan Ngo Hoang An
 *
 */
public class RouteStoreAn extends RouteStore {
	List<String> locationList = new ArrayList<String>();
	Map<String, Double> routeMap = new HashMap<String, Double>();
	
	public boolean addLocation(String locationName)
	{
		if(!locationList.contains(locationName.toUpperCase())){
			locationList.add(locationName.toUpperCase());
		}
		return true;
	}
	
	public boolean addPath(String fromLocation, String toLocation, double distance)
	{
		if(locationList.contains(fromLocation.toUpperCase()) == true 
			&& locationList.contains(toLocation.toUpperCase()) == true)
		{
			if(routeMap.get(toLocation.toUpperCase() + fromLocation.toUpperCase())!= null){
				routeMap.put((toLocation + fromLocation).toUpperCase(), distance);
				return true;
			}
			routeMap.put((fromLocation + toLocation).toUpperCase(), distance);
			return true;
		}
		else{
			return false;	
		}
	}
	
	public double getShortestDistance(String from, String to)
	{
		List<ArrayList<String>> routeList = getAllRoutes(from.toUpperCase(), to.toUpperCase());
		double shortestDistance = -1;
		for(ArrayList<String> route : routeList)
		{
			double distance = 0;
			for(int i=0; i < route.size()-1; i++)
			{
				distance += getDirectDistance(route.get(i),route.get(i+1));
			}
			if((shortestDistance == -1 || shortestDistance > distance) && distance != 0) shortestDistance = distance;
		}
		
		return shortestDistance;
	}
	
	public List<ArrayList<String>> getAllRoutes(String from, String to)
	{
		List<ArrayList<String>> routeList = new ArrayList<ArrayList<String>>();
		routeList.add(new ArrayList<String>());
		routeList.get(0).add(from);
		if(locationList.contains(from) && locationList.contains(to)){
			for(int i = 1; i < locationList.size(); i++)
			{
				List<ArrayList<String>> buildingRoutes = new ArrayList<ArrayList<String>>();
				for(ArrayList<String> route : routeList)
				{
					if(route.get(route.size()-1).equalsIgnoreCase(to))
					{
						buildingRoutes.add(route);
						continue;
					}
					for(String location : locationList)
					{
						if(!route.contains(location) && getDirectDistance(route.get(route.size()-1), location)!= -1)
						{
							@SuppressWarnings("unchecked")
							ArrayList<String> newRoute = (ArrayList<String>)route.clone();
							newRoute.add(location);
							buildingRoutes.add(newRoute);
						}
					}
				}
				routeList = buildingRoutes;
			}
		}
		return routeList;
	}
	
	public double getDirectDistance(String from, String to)
	{
		if(routeMap.get(from + to )!= null) return routeMap.get(from+to);
		else if(routeMap.get(to + from) != null) return routeMap.get(to + from);
		else return -1;
	}
	
	//Convenient methods for debugging
	public double printAllRoutes(List<ArrayList<String>> routeList)
	{
		double shortestDistance = -1;
		for(ArrayList<String> route : routeList)
		{
			double distance = 0;
			for(int i=0; i < route.size()-1; i++)
			{
				System.out.print(route.get(i)+route.get(i+1));
				distance += getDirectDistance(route.get(i),route.get(i+1));
			}
			System.out.println(" : " + (distance == 0 ? -1 : distance));
			if((shortestDistance == -1 || shortestDistance > distance) && distance != 0) shortestDistance = distance;
		}
		return shortestDistance;
	}
	public String toString(){
		return "An's Route Store";
	}
}
